package blog.controller;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.*;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;
import javax.microedition.rms.RecordStoreNotOpenException;

import blog.ConstString;
import blog.SysRuntime;
import blog.db.*;
import blog.gui.*;
import blog.network.BlogEngine;
import blog.util.*;

public class ActionManager extends Thread {
	private Vector actionList;
	private boolean bContinue;
	
	private static ActionManager _instance;
	public static synchronized ActionManager getInstance()
	{
		if ( _instance==null )
		{
			_instance = new ActionManager();
			_instance.start();
		}
		return _instance;
	}
	
	private ActionManager()
	{
		bContinue = true;
		actionList = new Vector();
	}
	
	public void addAction( IBaseGui gui, int actionId, Object param )
	{
		synchronized( actionList )
		{
			actionList.addElement( new StructAction(gui, actionId, param) );
			if ( actionList.size()==1 )
			{
				actionList.notify();
			}
		}
	}

	public void addAction( IBaseGui gui, int actionId )
	{
		addAction( gui, actionId, null );
	}

	public void run() {
		StructAction tmpAction = null;
		while( bContinue )
		{
			try
			{
				synchronized( actionList )
				{
					while( actionList.size()<=0 )
					{
						actionList.wait();
						if ( !bContinue )
						{
							return;
						}
					}
					tmpAction = (StructAction)actionList.elementAt(0);
					actionList.removeElementAt(0);
				}
				doAction(tmpAction);
			}
			catch( Exception e )
			{
			}
			tmpAction = null;
			System.gc();
		}
	}
	
	private void doAction( StructAction action )
	{
		switch( action.actionId )
		{
			case ConstAction.ACT_SPLASH_START:
			{
				//Open DB
				BlogAccountDB.openDB();
				action.m_gui.notifyChanged(new Integer(1));
				//...
				BlogEntryDB.openDB();
				action.m_gui.notifyChanged(new Integer(2));
				//...
				ShortCutDB.openDB();
				action.m_gui.notifyChanged(new Integer(3));
				//...
				BlogAccount[] accountList =  BlogAccountDB.getAll();
				for ( int i=0; i<accountList.length; i++ )
				{
					BlogEntryDB.setMaxSize(accountList[i].getId(), accountList[i].getLenEntryList(), false);
					BlogEntryDB.setMaxSize(accountList[i].getId(), accountList[i].getLenHistoryList(), true);
				}
				action.m_gui.notifyChanged(new Integer(4));
				BlogAccountManagerGui.getInstance().reloadData();
				action.m_gui.notifyChanged(new Integer(5));
				
				SysRuntime.guiManager.show( BlogAccountManagerGui.getInstance() );
				break;
			}
			case ConstAction.ACT_VERIFY_USER:
			{
				String[] params = (String[]) action.param;
				ProgressGui progress = new ProgressGui( ConstString.GUI_TITLE_USER_VERIFY_PROGRESS, "" );
				SysRuntime.guiManager.show( progress );
				
				HttpConnection hc = null;
				DataInputStream dis = null;
				RecordStore rs = null;
				byte[] data = null;
				String promptErrorString = "";
				try {
					progress.notifyChanged( new Integer(20) );
					
					if ( params[0]!=null && params[0].length()==RegUtils.reg.length )
					{
						//First verify local
						int i = params[1].indexOf('@');
						if ( i!=-1 )
						{
							String m = params[1].substring(0, i);
							String r = params[1].substring(i+1);
							
							if ( RegUtils.format(m, r).equals(params[0]) )
							{
								sss(rs, data, progress);
								return;
							}
						}
					}
					
					hc = (HttpConnection) Connector.open( StringUtils.combin(ConstString.VERIFY_URL, params[0], params[1]) );
					progress.notifyChanged( new Integer(40) );
					int respCode = hc.getResponseCode();
					if ( respCode==HttpConnection.HTTP_OK )
					{
						progress.notifyChanged( new Integer(60) );
						String resultCode = hc.getHeaderField("rc");
						progress.notifyChanged( new Integer(80) );
						if ( resultCode!=null && resultCode.equals("S") )
						{
							sss(rs, data, progress);
							return;
						}
						else
						{
							String failedStr = hc.getHeaderField("re");
							Alert alert = new Alert( "", StringUtils.combin(ConstString.GUI_VERIFY_USER_FAILURE, (failedStr==null||failedStr.length()==0)?"Unknown Error":failedStr), null, AlertType.ERROR);
							alert.setTimeout(5000);
							SysRuntime.guiManager.showAlert(alert, false);
							return;
						}
					}
					else if ( respCode==HttpConnection.HTTP_FORBIDDEN || respCode==HttpConnection.HTTP_NOT_FOUND )
					{
						promptErrorString = "Server Error occurs.";
					}
				} catch(Exception e) {
					promptErrorString = e.toString();
				}
				finally
				{
					data = null;
					if ( dis!=null )
					{
						try {
							dis.close();
						} catch (IOException e) {
						}
					}
					if ( hc!=null )
					{
						try {
							hc.close();
						} catch (IOException e) {
						}
					}
					if ( rs!=null )
					{
						try {
							rs.closeRecordStore();
						} catch (RecordStoreNotOpenException e) {
						} catch (RecordStoreException e) {
						}
						rs = null;
					}
				}
				Alert alert = new Alert( "", StringUtils.combin(ConstString.GUI_VERIFY_USER_FAILURE, "Error: "+promptErrorString), null, AlertType.ERROR);
				alert.setTimeout(5000);
				SysRuntime.guiManager.showAlert(alert, false);
				break;
			}
			case ConstAction.ACT_GET_BLOG_LIST:
			{
				ProgressGui progress = new ProgressGui( ConstString.GUI_TITLE_GET_BLOG_LIST, "" );
				SysRuntime.guiManager.show( progress );
				Vector result;
				String errorString = "";
				try {
					result = BlogEngine.getInstance().getUsersBlogsList(progress);
					BlogSelectGui nextScreen = BlogSelectGui.getInstance();
					nextScreen.reloadData(result, BlogSelectGui.TYPE_USER_CLICK);
					SysRuntime.guiManager.show( nextScreen, false );
					return;
				} catch (Exception e) {
					errorString = e.toString();
				}
				Alert nextScreen = new Alert(ConstString.GUI_TITLE_PROMPT, StringUtils.combin(ConstString.GUI_GET_BLOG_LIST_FAILED, errorString), null, AlertType.WARNING);
				nextScreen.setTimeout( 5000 );
				SysRuntime.guiManager.showAlert(nextScreen, false);
				break;
			}
			case ConstAction.ACT_FILE_SELECTOR:
			{
				MediaFileSelectorImpl nextScreen = new MediaFileSelectorImpl();
				FileSystemRegistry.addFileSystemListener( nextScreen );
				nextScreen.resetRoots( ); //display the root directories
				SysRuntime.guiManager.show(nextScreen);
				break;
			}
			case ConstAction.ACT_POST_BLOG:
			{
				ProgressGui progress = new ProgressGui( ConstString.GUI_TITLE_POST_BLOG_ENTRY, "" );
				SysRuntime.guiManager.show( progress, action.m_gui==BlogEntryListGui.getInstance() );
				BlogEntry entry = (BlogEntry) action.param;
				String errorString = "";
				try {
					BlogEngine.getInstance().postEntry(entry, progress);
					entry.setPublishOk(true);
					BlogEntryDB.update(entry);
					BlogEntryListGui.getInstance().reloadData();
					SysRuntime.guiManager.back();
					return;
				} catch (Exception e) {
					errorString = e.toString();
				}
				Alert nextScreen = new Alert(ConstString.GUI_TITLE_PROMPT, StringUtils.combin(ConstString.GUI_POST_BLOG_FAILED, errorString), null, AlertType.WARNING);
				nextScreen.setTimeout( 5000 );
				SysRuntime.guiManager.showAlert(nextScreen, false);
				break;
			}
			case ConstAction.ACT_VIDEO_SELECTOR:
			{
				try
				{
					CameraDisplay nextScreen = new CameraDisplay();
					SysRuntime.guiManager.show(nextScreen);
				}
				catch(Exception e)
				{
					Alert alert = new Alert(ConstString.GUI_TITLE_PROMPT, ConstString.GUI_CAMERA_DISPLAY_INIT_ERROR, null, AlertType.WARNING);
					alert.setTimeout( 5000 );
					SysRuntime.guiManager.showAlert(alert, true);
					return;
				}
				break;
			}
			case ConstAction.ACT_VIDEO_CAPTURE:
			{
				BlogEntryGui.getInstance().camFinished((CameraDisplay)action.m_gui);
				
				SysRuntime.guiManager.back();
				break;
			}
			case ConstAction.ACT_FILE_SELECT_FINISH:
			{
				MediaFileSelectorImpl mfs = (MediaFileSelectorImpl) action.param;
				mfs.doNotifyOpComplete();
				SysRuntime.guiManager.back();
				break;
			}
			case ConstAction.ACT_GET_BLOG_WHEN_ADD:
			{
				ProgressGui progress = new ProgressGui( ConstString.GUI_TITLE_GET_BLOG_LIST, "" );
				SysRuntime.guiManager.show( progress );
				BlogAccount account = (BlogAccount) action.param;
				Vector result;
				String errorString = "";
				try {
					result = BlogEngine.getInstance().getUsersBlogsList(account, progress);
					BlogSelectGui nextScreen = BlogSelectGui.getInstance();
					nextScreen.reloadData(result, BlogSelectGui.TYPE_ADD_VERIFY);
					nextScreen.setAccount( account );
					SysRuntime.guiManager.show( nextScreen, false );
					return;
				} catch (Exception e) {
					errorString = e.toString();
				}
				Alert nextScreen = new Alert(ConstString.GUI_TITLE_PROMPT, StringUtils.combin(ConstString.GUI_GET_BLOG_LIST_FAILED, errorString), null, AlertType.WARNING);
				nextScreen.setTimeout( 5000 );
				SysRuntime.guiManager.showAlert(nextScreen, false);
				break;
			}
			case ConstAction.ACT_GET_BLOG_WHEN_EDIT:
			{
				ProgressGui progress = new ProgressGui( ConstString.GUI_TITLE_GET_BLOG_LIST, "" );
				SysRuntime.guiManager.show( progress );
				BlogAccount account = (BlogAccount) action.param;
				Vector result;
				String errorString = "";
				try {
					result = BlogEngine.getInstance().getUsersBlogsList(account, progress);
					BlogSelectGui nextScreen = BlogSelectGui.getInstance();
					nextScreen.reloadData(result, BlogSelectGui.TYPE_EDIT_VERIFY);
					nextScreen.setAccount( account );
					SysRuntime.guiManager.show( nextScreen, false );
					return;
				} catch (Exception e) {
					errorString = e.toString();
				}
				Alert nextScreen = new Alert(ConstString.GUI_TITLE_PROMPT, StringUtils.combin(ConstString.GUI_GET_BLOG_LIST_FAILED, errorString), null, AlertType.WARNING);
				nextScreen.setTimeout( 5000 );
				SysRuntime.guiManager.showAlert(nextScreen, false);
				break;
			}
		}
	}

	private void sss( RecordStore rs, byte[] data, ProgressGui progress ) throws RecordStoreFullException, RecordStoreNotFoundException, RecordStoreException
	{
		rs = RecordStore.openRecordStore( ConstString.DB_NAME_USER_VERIFY, true );
		data = "true user".getBytes();
		if ( rs.getNumRecords()>0 )
		{
			rs.setRecord( 1, data, 0, data.length );
		}
		else 
		{
			rs.addRecord(data, 0, data.length );
		}
		progress.notifyChanged( new Integer(100) );
		SysRuntime.registedUser = true;
		
		Alert alert = new Alert(ConstString.GUI_TITLE_PROMPT, ConstString.GUI_REGISTER_SUCCESS, null, null);
		alert.setType(AlertType.INFO);
		alert.setTimeout(5000);
		alert.setCommandListener(new CommandListener(){
			public void commandAction(Command arg0, Displayable arg1) {
				if ( arg0==Alert.DISMISS_COMMAND )
				{
					SysRuntime.guiManager.show( new SplashGui(), false );
				}
			}});
		SysRuntime.guiManager.show(alert, false);
	}

	static class StructAction
	{
		public IBaseGui m_gui;
		public int actionId;
		public Object param;
		
		public StructAction(IBaseGui m_gui, int actionId, Object param) {
			super();
			this.m_gui = m_gui;
			this.actionId = actionId;
			this.param = param;
		}
		
	}
}
